<?php
//+----------------------------------------------------------------------
//| ThinkPHP [ WE CAN DO IT JUST THINK IT ]
//+----------------------------------------------------------------------
//| Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
//+----------------------------------------------------------------------
//| Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
//+----------------------------------------------------------------------
//| Author: liu21st <liu21st@gmail.com>
//+----------------------------------------------------------------------
//$Id: Think.class.php 2791 2012-02-29 10:08:57Z liu21st $

/**
 +------------------------------------------------------------------------------
 * ThinkPHP Portal类
 +------------------------------------------------------------------------------
 * @category   Think
 * @package  Think
 * @subpackage  Core
 * @author    liu21st <liu21st@gmail.com>
 * @version   $Id: Think.class.php 2791 2012-02-29 10:08:57Z liu21st $
 * @last modify 2012-12-03 14:34:01 by mashanling
 +------------------------------------------------------------------------------
 */
class Think {

    /**
     * 实例
     *
     * @var array
     * @access private
     */
    private static $_instance = array();

    /**
     *
     * 读取配置信息 编译项目
     *
     * @last modify 2012-12-03 15:01:18 by mashanling
     *
     * @access static,private
     *
     * @return void 无返回值
     */
    static private function buildApp() {
        C(include THINK_PATH . 'Conf/convention.php');//加载底层惯例配置文件

        //读取运行模式
        $mode   = defined('MODE_NAME') ? include(MODE_PATH . strtolower(MODE_NAME) . '.php') : array();

        if (isset($mode['config'])) {//加载模式配置文件
            C(is_array($v = $mode['config']) ? $v : include($v));
        }

        is_file($filename = CONF_PATH . 'config.php') && C(include $filename);//加载项目配置文件

        L(include THINK_PATH . 'Lang/' . strtolower(C('DEFAULT_LANG')) . '.php');//加载框架底层语言包

        if (C('APP_TAGS_ON')) {//加载模式系统行为定义

            if (isset($mode['extends'])) {
                C('extends', is_array($v = $mode['extends']) ? $v : include($v));
            }
            else {//默认加载系统行为扩展定义
                C('extends', include(THINK_PATH . 'Conf/tags.php'));
            }
        }


        if (isset($mode['tags'])) {//加载应用行为定义
            C('tags', is_array($v = $mode['tags']) ? $v : include($v));
        }
        elseif (is_file($filename = CONF_PATH . 'tags.php')) {//默认加载项目配置目录的tags文件定义
            C('tags', include($filename));
        }

        $compile   = '';

        if (isset($mode['core'])) {//读取核心编译文件列表
            $list = $mode['core'];
        }
        else {
            $list = array(
                CORE_PATH . 'Core/Log.class.php',  //日志处理类
                CORE_PATH . 'Core/Dispatcher.class.php',  //URL调度类
                CORE_PATH . 'Core/App.class.php',  //应用程序类
                CORE_PATH . 'Core/Action.class.php',  //控制器类
                CORE_PATH . 'Core/View.class.php' //视图类
            );
        }

        //项目追加核心编译列表文件
        is_file($filename = CONF_PATH . 'core.php') && $list = array_merge($list, include($filename));

        foreach ($list as $file){

            if(is_file($file))  {
                require_cache($file);
                !APP_DEBUG && $compile .= compile($file);
            }
        }

        if(is_file($filename = COMMON_PATH . 'common.php')) {//加载项目公共文件
            include $filename;
            !APP_DEBUG && $compile .= compile($file);
        }


        if (isset($mode['alias'])) {//加载模式别名定义
            $alias = is_array($mode['alias']) ? $mode['alias'] : include $mode['alias'];
            alias_import($alias);
            !APP_DEBUG && $compile .= 'alias_import(' . var_export($alias, true) . ');';
        }

        //加载项目别名定义
        if (is_file($filename = CONF_PATH . 'alias.php')) {
            $alias = include $filename;
            alias_import($alias);
            !APP_DEBUG && $compile .= 'alias_import(' . var_export($alias, true) . ');';
        }

        if(APP_DEBUG) {
            C(include THINK_PATH . 'Conf/debug.php');//调试模式加载系统默认的配置文件
            $status  =  C('APP_STATUS');//读取调试模式的应用状态
            is_file($filename = CONF_PATH . $status . '.php') && C(include $filename);//加载对应的项目配置文件,增加开发模式配置定义
        }
        else{//部署模式下面生成编译文件
            build_runtime_cache($compile);
        }
    }//end buildApp

    /**
     *
     * 系统自动加载ThinkPHP类库,并且支持配置自动加载路径
     *
     * @last modify  2012-12-03 15:12:47 by mashanling
     *
     * @access static,public
     *
     * @param string $class 类名
     *
     * @return null
     */
    static public function autoload($class) {

        if (alias_import($class)) {//检查是否存在别名定义
            return;
        }

        if (substr($class, -8) == 'Behavior') {//加载行为
            $v = 'Behavior/' . $class . '.class.php';

            if (require_cache(CORE_PATH . $v) ||
                require_cache(EXTEND_PATH . $v) ||
                require_cache(LIB_PATH . $v) ||
                (defined('MODE_NAME') && require_cache(MODE_PATH . ucwords(MODE_NAME) . '/' . $v))) {
                return;
            }
        }
        elseif (substr($class, -5) == 'Model') { //加载模型
            $v = 'Model/' . $class . '.class.php';

            if (require_cache(LIB_PATH . $v) ||
                require_cache(EXTEND_PATH . $v)) {
                return;
            }
        }
        elseif (substr($class, - 6) == 'Action') { //加载控制器
            $v = 'Action/' . $class . '.class.php';

            if (require_cache(LIB_PATH . $v) ||
                require_cache(EXTEND_PATH . $v) ) {
                return;
            }
        }

        //根据自动加载路径设置进行尝试搜索
        $paths = explode(',', C('APP_AUTOLOAD_PATH'));

        foreach ($paths as $path){

            if (import($class, $path)) {//如果加载类成功则返回
                return;
            }
        }
    }//end autoload

    /**
     *
     * 取得对象实例 支持调用类方法
     *
     * @last modify  2012-12-03 15:20:08 by mashanling
     *
     * @access static,public
     *
     * @param string $class  类名
     * @param string $method 类方法
     *
     * @return object 类实例
     */
    static public function instance($class, $method = '') {
        $identify = $class . $method;

        if (!isset(self::$_instance[$identify])) {

            if (class_exists($class)) {
                $o = new $class();

                if (!empty($method) && method_exists($o, $method)) {
                    self::$_instance[$identify] = call_user_func_array(array(&$o, $method), array());
                }
                else {
                    self::$_instance[$identify] = $o;
                }
            }
            else {
                halt(L('_CLASS_NOT_EXIST_') . ':' . $class);
            }
        }

        return self::$_instance[$identify];
    }

    /**
     * 项目入口，应用程序初始化
     *
     * @last modify  2012-12-03 15:23:15 by mashanling
     *
     * @access static,public
     *
     * @return void 无返回值
     */
    static public function start() {
        //设定错误和异常处理
        register_shutdown_function('fatal_error');
        set_error_handler('error_handler');
        set_exception_handler('exception_handler');
        spl_autoload_register(array('Think', 'autoload'));//注册AUTOLOAD方法

        if (APP_DEBUG || !is_file(RUNTIME_FILE)) {//预编译项目
            self::buildApp();//预编译项目
        }
        App::run();//运行应用
    }

    /**
     * 获取属性
     *
     * @last modify  2012-12-03 15:24:05 by mashanling
     *
     * @access public
     *
     * @param string $name 属性名称
     *
     * @return mixed 属性存在，返回属性值，否则返回null
     */
    public function __get($name) {
        return isset($this->$name) ? $this->$name : null;
    }

    /**
     * 设置属性
     *
     * @last modify  2012-12-03 15:25:45 by mashanling
     *
     * @access public
     *
     * @param string $name 属性名称
     * @param mixed  属性值
     *
     * @return void 无返回值
     */
    public function __set($name, $value) {
        property_exists($this, $name) && $this->$name = $value;
    }
}